#ifndef COMMON_H
#define COMMON_H
// /*
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <cstring>


#define sqr(x) ((x)*(x))
#define zero (1e-12)
#define EPS (1e-8)

using namespace std;

struct Bmp;

struct RGB{
    RGB(){ r = g = b = 0;}
    RGB(double x, double y, double z){r = x; g = y; b = z;}
    RGB operator*(const RGB &a){RGB tmp; tmp.r = r * a.r; tmp.g = g * a.g; tmp.b = b * a.b; return tmp;}
    RGB operator+(const RGB &a){RGB tmp; tmp.r = r + a.r; tmp.g = g + a.g; tmp.b = b + a.b; return tmp;}
    RGB &operator+=(const RGB &a){r += a.r; g += a.g; b += a.b; return *this;}
    RGB operator*(const double &a){RGB tmp; tmp.r = r * a; tmp.g = g * a; tmp.b = b * a; return tmp;}
    RGB operator/(const double &a){RGB tmp; tmp.r = r / a; tmp.g = g / a; tmp.b = b / a; return tmp;}

    void check(){
        double mm = max(max(r, g), b);
        if (mm > 1){
            r /= mm;
            g /= mm;
            b /= mm;
        }
//        if (r>1) r=1;
//        if (g>1) g=1;
//        if (b>1) b=1;
    }
    double r,g,b;
};

struct Vec{

    double x,y,z;
    Vec(){x = y = z = 0.0;}
    Vec(double xx,double yy,double zz){x=xx;y=yy;z=zz;}
    Vec operator=(const Vec &a){x=a.x;y=a.y;z=a.z;return a;}
    double length()const{return sqrt(x*x+y*y+z*z);}
    double sqrlength()const{return (x*x+y*y+z*z);}
    Vec normalize()const{double inv=1/length();Vec nee(inv*x,inv*y,inv*z);return nee;} //返回单位向量
    Vec negate()const{Vec nee(-x,-y,-z);return nee;}
    Vec operator+(const Vec &b)const{Vec nee;nee.x=x+b.x;nee.y=y+b.y;nee.z=z+b.z;return nee;}
    Vec operator-(const Vec &b)const{Vec nee;nee.x=x-b.x;nee.y=y-b.y;nee.z=z-b.z;return nee;}
    double operator*(const Vec &b)const{double nee=x*b.x+y*b.y+z*b.z;return nee;}//点乘
    double& operator[](const int &i){
        if (i == 0) return x;
        else
        if (i == 1) return y;
        else
        if (i == 2) return z;
        else{
            cout <<"error cmmon.h 56!" << endl;
            return x;
        }
    }
    Vec operator/(const double &b)const{Vec nee;nee.x=x/b;nee.y=y/b;nee.z=z/b;return nee;}
    Vec operator*(const double &b)const{Vec nee;nee.x=x*b;nee.y=y*b;nee.z=z*b;return nee;}
    Vec cross(const Vec &b)const{  //叉乘
        Vec nee;
        nee.x=y*b.z-z*b.y;
        nee.y=z*b.x-x*b.z;
        nee.z=x*b.y-y*b.x;
        return nee;
    }
};

struct Ray{
    Vec ori, dir;
    Ray(Vec a,Vec b){ori = a; dir = b;}
    Vec getpoint(double a) const{
        return (ori + (dir * a));
    }
};

struct Material{
    Material(){
        reflect = 0.5;
        refract = 0;
        diffuse = 0.5;
        specular = 0.1;
        color = RGB(0, 1, 0);
        texture = 0;
    }

    Material(double x, double y, double z, double w, RGB color):
        reflect(x),
        refract(y),
        diffuse(z),
        specular(w),
        color(color){
        texture = 0;
    }

    double reflect, refract, diffuse, specular;
    void setTexture(string file);
    RGB getColor(double x, double y);
    RGB color;
    bool texture;
    Bmp *bmp;
};

struct Matrix{
    Matrix(){
        memset(matrix, 0 ,sizeof(matrix));
    }
    void operator +=(const Matrix& a){
        for (int i = 0 ; i < 4; i++){
            for (int j = 0 ; j < 4; j++){
                matrix[i][j] += a.matrix[i][j];
            }
        }
    }

    void operator -=(const Matrix& a){
        for (int i = 0 ; i < 4; i++){
            for (int j = 0 ; j < 4; j++){
                matrix[i][j] -= a.matrix[i][j];
            }
        }
    }
    Vec solve();

    double matrix[4][4];
};

ostream& operator <<(ostream& os, Vec a);

ostream& operator <<(ostream& os, Ray ray);

ostream& operator <<(ostream& os, RGB col);

ostream& operator <<(ostream& os, Matrix mm);

double ran();

int getFather(int x, int * father);


#endif // COMMON_H

